<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      // 工厂函数：模子，同一个工厂，生产出独立的产品，产品最初的属性方法都是一样的
      // 只有函数有protoType对象
      function A(name, age) {
        // 显式的声明在了构造函数里
        this.name = name;
        this.age = age;
        this.getMl = function() {
          return `${this.name}今年${this.age}岁了`;
        };
      }

      // 函数被new以后，该函数叫构造函数
      const ml = new A("于朦胧", 27);
      A.prototype.job = "歌手";
      A.prototype.run = function() {
        return `${this.name}身为${this.job}，竟然跑了1005米，用时2.5分钟`;
      };
      // new 这个动作就叫实例化，返回的对象就是实例化对象
      console.log(ml.run());

      // class 类 基于 函数的prototype封装的
      class Hua {
        // 构造函数
        constructor(name, age) {
          this.name = name;
          this.age = age;
          this.getHua = function() {
            return `${this.name}今年${this.age}岁了`;
          };
        }
        // 在class内部在构造函数外部写的属性和方法就等价于在函数的prototype上加的
        job = "歌手";
        run() {
          return `${this.name}是一个${this.job}，和${ml.name}一样深受大家的喜欢`;
        }
      }
      const hua = new Hua("华晨宇", 28);
      console.log(hua.run());
      // 继承 封装 多态
      // zl 叫派生类，基于Hua派生出来的
      // zl叫子类，Hua叫父类
      class zl extends Hua {
        // 派生类如果需要显示的去写构造函数，就必须调用super方法
        constructor(name, age) {
          super();
          this.name = name;
          this.age = age;
          this.getThis = () => {
            return `${this.name}今天过${this.age}岁生日`;
          };
        }
      }
      const obj = new zl("昭林", 28);
      console.log(obj.getThis());
    </script>
  </body>
</html>
